package org.wlgzs.office_exam_student.servlet;

import java.io.IOException;
import java.io.Writer;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wlgzs.office_exam_student.permission.Authentication;
import org.wlgzs.office_exam_student.service.*;
import org.wlgzs.office_exam_student.view.View;
import org.wlgzs.office_exam_student.view.ViewFactory;
import org.wlgzs.office_exam_student.view.freemarker.FMViewFactory;


/**
*@author song(mejeesong@qq.com)
*2018年1月24日
*所有Servlet都需要继承此类.
*本类为子类处理基础操作且提供：
*1.logger
*2.简便的方法
*3.相关的Service(如：用户服务：UserService)
*
*/
public class BaseServlet extends HttpServlet {

	protected static final long serialVersionUID = 1L;
	
	//试图工厂类，用于获得试图（即模板）
	private static ViewFactory vf = null;
	private static Object vfLock = new Object();
	//存放每个请求的相关对象
	public final static ThreadLocal<MyRequestWrapper> threadReq = new ThreadLocal<>();
	public final static ThreadLocal<HttpServletResponse> threadRes = new ThreadLocal<>();
	//logger,每个类被创建时自动生成
	protected Logger logger;
	//上下文路径
	protected String contextPath = "";
	
	protected OfficeResolverService officeResolverService = new OfficeResolverService(20280,4);
	protected LoginFailLogService loginFailLogService = new LoginFailLogService();
	protected LoginLogService loginLogService = new LoginLogService();
	protected UserService userService = new UserService();
	protected OperateQuestionService operateQuestionService =new OperateQuestionService();
	protected ChoiceQuestionService choiceQuestionService =new ChoiceQuestionService();
	protected ExamService examService = new ExamService();
    protected ExamQuestionService examQuestionService=new ExamQuestionService();
    protected ScoreService scoreService=new ScoreService();

	public BaseServlet() {
		logger = LoggerFactory.getLogger(this.getClass());
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		super.init(config);
		contextPath = config.getServletContext().getContextPath();
		if (vf == null) {
			synchronized (vfLock) {
				if(vf == null) {
					vf = new FMViewFactory(config.getServletContext().getRealPath("/WEB-INF/template"));
					Map<String,String> datas = new HashMap<>();
					datas.put("contextPath",contextPath);
					vf.loadConfig(datas);
				}
			}
		}
	}
	
	@Override
	protected final void service(javax.servlet.http.HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		MyRequestWrapper request = new MyRequestWrapper(req); 
		threadReq.set(request);
		threadRes.set(resp);
		super.service(request, resp);
	}
	
	protected final void renderString(String str) {
		try {
			threadRes.get().getWriter().append(str);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	//渲染视图，为子类调用
	protected final void render(String name) {
		try {
			render(name,threadRes.get().getWriter());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	protected final void render(String name,Writer out) {
		View view = vf.getView(name);
		Map<String,Object> data = new HashMap<>();
		
		MyRequestWrapper req = threadReq.get();
		Map<String, Object> reqData = req.getData();
		HttpSession session = req.getSession();
		ServletContext context = session.getServletContext();
		Enumeration<String> keys = context.getAttributeNames();
		while (keys.hasMoreElements()) {
			String key = keys.nextElement();
			data.put(key, context.getAttribute(key));
		}
		keys = session.getAttributeNames();
		while (keys.hasMoreElements()) {
			String key = keys.nextElement();
			data.put(key, session.getAttribute(key));
		}
		data.putAll(reqData);
		try {
			view.render(data, out);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	protected final void render(Map<String,Object> data,String name,Writer out) throws Exception {
		View view = vf.getView(name);
		view.render(data, out);
	}
	protected final void redirect(String uri) {
		if(uri.startsWith("/")) {
			uri=contextPath + uri;
		}
		try {
			threadRes.get().sendRedirect(uri);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	*@author song(mejeesong@qq.com)
	*2018年1月24日
	*对Request对象的包装，便于模板使用，不必在意
	*/
	public class MyRequestWrapper extends HttpServletRequestWrapper {

		private Map<String, Object> data = new HashMap<>();
		
		public MyRequestWrapper(javax.servlet.http.HttpServletRequest req) {
			super(req);
		}
		
		public Map<String,Object> getData(){
			return data;
		}

		@Override
		public void setAttribute(String name, Object o) {
			data.put(name, o);
		}

		@Override
		public Object getAttribute(String name) {
			return data.get(name);
		}
	}
	
	/**
	*@author song(mejeesong@qq.com)
	*@date 2018年1月25日
	*@param role Role类的一个属性值
	*@return 是否是此角色
	*
	*/
	protected boolean is(String role) {
		return Authentication.is(threadReq.get(), role);
	}
	
	/**
	*@author song(mejeesong@qq.com)
	*@date 2018年1月25日
	*@param power Power类的一个字段值
	*@return 是否拥有此权限
	*
	*/
	protected boolean can(String power) {
		return Authentication.is(threadReq.get(), power);
	}
}
